package com.vf.cloud.paas.app.agent.common.server.signalling.pool;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.util.regex.Pattern;

import com.jfinal.kit.StrKit;
import com.vf.cloud.paas.common.cirrus.Cirrus;
import com.vf.cloud.paas.common.service.impl.RedisImpl;
import com.vf.cloud.paas.common.util.SpringContextHolder;

import io.netty.channel.ChannelHandlerContext;

public class StreamerPool {

	public static void put(String token, ChannelHandlerContext ctx) {
		Cirrus.Concurrent_Streamer.put(token, ctx);
		SpringContextHolder.getBean(RedisImpl.class).add(ctx.channel().id().asLongText(), token);
	}

	public static void removeByChannelId(String channelId) {
		if (SpringContextHolder.getBean(RedisImpl.class).hasKey(channelId)) {
			String token = SpringContextHolder.getBean(RedisImpl.class).get(channelId);
			if (!StrKit.isBlank(token) && Cirrus.Concurrent_Streamer.containsKey(token)) {
				ChannelHandlerContext ctx = Cirrus.Concurrent_Streamer.get(token);
				if (ctx != null)
					ctx.close();
				Cirrus.Concurrent_Streamer.remove(token);
			}
			SpringContextHolder.getBean(RedisImpl.class).delete(channelId);
		}
	}

	public static void removeByToken(String token) {
		if (Cirrus.Concurrent_Streamer.containsKey(token)) {
			ChannelHandlerContext ctx = Cirrus.Concurrent_Streamer.get(token);
			if (ctx != null) {
				SpringContextHolder.getBean(RedisImpl.class).delete(ctx.channel().id().asLongText());
			}
			ctx.close();
			Cirrus.Concurrent_Streamer.remove(token);
		}
	}

	public static String getTokenByChannelId(String ChannelId) {
		if (SpringContextHolder.getBean(RedisImpl.class).hasKey(ChannelId)) {
			return SpringContextHolder.getBean(RedisImpl.class).get(ChannelId);
		}
		return "";
	}

	public static ChannelHandlerContext getByToken(String token) {
		if (Cirrus.Concurrent_Streamer.containsKey(token)) {
			return Cirrus.Concurrent_Streamer.get(token);
		}
		return null;
	}

	public static boolean containsToken(String token) {
		return Cirrus.Concurrent_Streamer.containsKey(token);
	}

	public static void killByToken(String token) {
		if (Cirrus.Concurrent_Streamer.containsKey(token)) {
			ChannelHandlerContext ctx = Cirrus.Concurrent_Streamer.get(token);
			if (ctx != null) {
				InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
				String clientPort = String.valueOf(insocket.getPort());
				String pid = getPid(clientPort);
				if (!StrKit.isBlank(pid)) {
					kill(pid);
				}
				ctx.close();
			}
		}

	}

	public static String getPid(String port) {
		try {
			Runtime runtime = Runtime.getRuntime();
			Process process = runtime.exec("cmd /c netstat -ano | findstr " + port);
			BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
			String line = null;
			String pid = null;
			while ((line = br.readLine()) != null) {
				String[] s = Pattern.compile("\\s+").matcher(line).replaceAll(";").split(";");
				if (s != null && s[2].contains(port)) {
					pid = s[s.length - 1];
					break;
				}
			}
			if (!StrKit.isBlank(pid)) {
				return pid;
			}
		} catch (Exception e) {
		}
		return "";
	}

	private static void kill(String pid) {
		if (!StrKit.isBlank(pid)) {
			try {
				Runtime runtime = Runtime.getRuntime();
				runtime.exec(String.format("cmd /c taskkill/F /PID %s ", pid));
			} catch (Exception e) {
			}
		}
	}

	public static void closeByChannelHandlerContext(ChannelHandlerContext ctx) {
		InetSocketAddress insocket = (InetSocketAddress) ctx.channel().remoteAddress();
		String clientPort = String.valueOf(insocket.getPort());
		String pid = getPid(clientPort);
		if (!StrKit.isBlank(pid)) {
			kill(pid);
		}
	}

}
